package org.fhm.zdte.server.cmd;

import org.fhm.substrate.annotation.Component;
import org.fhm.substrate.annotation.Setup;
import org.fhm.substrate.service.LoggerHandler;
import org.fhm.substrate.standard.ILogger;
import org.fhm.zdte.common.ability.IGetIdentification;
import org.fhm.zdte.common.ability.IGetTargetAddress;
import org.fhm.zdte.common.constant.protocol.PacketType;
import org.fhm.zdte.common.constant.protocol.ResponseMessageType;
import org.fhm.zdte.common.pojo.Address;
import org.fhm.zdte.common.pojo.UserGroup;
import org.fhm.zdte.common.protocol.AbstractMessageStandard;
import org.fhm.zdte.common.service.message.AbstractReceiveMessageManager;
import org.fhm.zdte.common.service.message.AbstractSendMessageManager;
import org.fhm.zdte.common.util.CommonUtil;
import org.fhm.zdte.server.ability.IGetOnlineUserGroup;

import java.util.Map;


/**
 * Oline command processor.
 *
 * @author 谭波
 * @since 2023/11/6
 */
@Component("ONLINE")
public class OnlineServerCmd extends AbstractServerCmd implements IGetOnlineUserGroup, IGetTargetAddress {

    private final ILogger logger = LoggerHandler.getLogger(OnlineServerCmd.class);

    @Setup
    private CommonUtil commonUtil;

    @Setup
    private IGetIdentification iGetIdentification;

    @Setup
    private Map<String, AbstractReceiveMessageManager> abstractReceiveMessageManagerMap;

    @Setup
    private Map<String, AbstractSendMessageManager> abstractSendMessageManagerMap;

    @Override
    public void receiveCmd(
            Address address, AbstractMessageStandard message
    ) {
        onlineUserContainer.entrySet().stream().filter(
                en -> en.getValue().equals(address)
        ).findFirst().ifPresent(en -> {
            String oldUserId;
            onlineUserContainer.remove((oldUserId = en.getKey()));
            onlineTimeRecordContainer.remove(oldUserId);
            abstractReceiveMessageManagerMap.values().forEach(manage -> manage.clearMessageBuffer(oldUserId));
            abstractSendMessageManagerMap.values().forEach(manage -> manage.clearMessageBuffer(oldUserId));
        });
        String from = commonUtil.getIdentification(onlineUserContainer.keySet());
        if (onlineUserContainer.size() >= serverInitialConfiguration.getMaxUserNumber()) {
            iChannelDispatcher.obtainChannelManager(address)
                    .sendMessage(abstractMessageWrappers.getFailAckMessageByPacketType(
                            PacketType.ONLINE, ResponseMessageType.USER_LIMIT, null,
                            iGetIdentification.getIdentification(), from, null,
                            from), address);
            return;
        }
        onlineUserContainer.put(from, address);
        onlineTimeRecordContainer.put(from, commonUtil.getCurTimeMillisSecond());
        logger.info("the address is IP: {}, PORT: {}. the client that identification is {} has been online", address.getIpv4(), address.getPort(), from);
        sendDealTask.getTaskAndSubmit(
                abstractMessageWrappers.getAckMessageByPacketType(
                        PacketType.ONLINE, null, iGetIdentification.getIdentification(),
                        from, null, null,
                        ""), address
        );
    }

    @Override
    public Address getTargetAddress(String target) {
        return onlineUserContainer.get(target);
    }

    @Override
    public UserGroup getOnlineUserGroup(String from) {
        return new UserGroup(onlineUserContainer, from);
    }
}
